SwiftUI View を UICollectionViewCell で使う

iOS 16 以上

UIHostingConfiguraton を使う

iOS 15 以下

wrapper を作る

final class HostingCell<Content: View>: UICollectionViewCell {
    private let hostingController = UIHostingController<Content?>(rootView: nil)

    override init(style: UICollectionViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        hostingController.view.backgroundColor = .clear
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    func set(rootView: Content, parentController: UIViewController) {
        self.hostingController.rootView = rootView
        self.hostingController.view.invalidateIntrinsicContentSize()

        let requiresControllerMove = hostingController.parent != parentController
        if requiresControllerMove {
            parentController.addChild(hostingController)
        }

        if !contentView.subviews.contains(hostingController.view) {
            contentView.addSubview(hostingController.view)
            hostingController.view.edgesToSuperView() // TinyConstraints 利用
        }

        if requiresControllerMove {
            hostingController.didMove(toParent: parentController)
        }
    }
}

参考: 新機能「ショート動画」をTCAで実装したので、その実装テクニックをご紹介します - Uzabase for Engineers

SwiftUI UIKit